using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace AnalyStock.DataManage;

/// <summary>
///     下载在线数据通用Template
/// </summary>
/// <typeparam name="T"></typeparam>
internal interface IDownloadDataOnline<T>
{
    Task<IList<T>> DownloadOnlineAsync(params string[] args);
}

internal class DownloadDataOnline<T> : IDownloadDataOnline<T> where T : class, new()
{
    public virtual async Task<IList<T>> DownloadOnlineAsync(params string[] args)
    {
        await Task.Delay(5).ConfigureAwait(false);
        return new List<T>();
    }
}

internal static class DataTableToCollection
{
    public static IList<T> ConvertTableToList<T>
        (this DataTable dtResult, bool isCustomAttribute = false) where T : class, new()
    {
        List<T> lstT = new();
        foreach (DataRow dr in dtResult.Rows)
        {
            T t = new();
            foreach (var pi in typeof(T).GetProperties())
            {
                var piName = isCustomAttribute
                    ? pi.GetCustomAttribute<DisplayAttribute>().Name
                    : pi.Name.ToLower();
                if (dtResult.Columns.Contains(piName)
                    && dr.Field<object>(piName) is string fieldValue)
                {
                    pi.SetValue(t, Convert.ChangeType(fieldValue, pi.PropertyType));
                }
            }

            lstT.Add(t);
        }

        return lstT;
    }
}

///

#region

/// <summary>
///     下载股票基本数据集合，参数args:null,null,null
/// </summary>
internal class DownloadOnline_StockBasic : DownloadDataOnline<StockBasic>
{
    public override async Task<IList<StockBasic>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            { "list_status", "L" }
        };
        var fields = "ts_code,symbol,name,area,industry,market,list_date,cnspell,exchange";
        using var dtResulte = await UtilityOfTuShare
            .GetTradeDataAsync("stock_basic", paramKey, fields)
            .ConfigureAwait(false);
        return dtResulte.ConvertTableToList<StockBasic>();
    }
}

/// <summary>
///  参数args:   null, null,tradedate
/// </summary>
internal class DownloadOnline_BakDaily : DownloadDataOnline<BakDaily>
{
    public override async Task<IList<BakDaily>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            { "trade_date", args[0] }
        };
        using var dtResulte =
            await UtilityOfTuShare.GetTradeDataAsync("bak_daily", paramKey).ConfigureAwait(false);
        return dtResulte.ConvertTableToList<BakDaily>();
    }
}

/// <summary>
///  参数args:   startdate, enddate, null
/// </summary>
internal class DownloadOnline_TradeCalendar : DownloadDataOnline<TradeCalendar>
{
    public override async Task<IList<TradeCalendar>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            { "start_date", args[0] },
            { "end_date", args[1] },
            { "exchange", "SSE" }, //市场             
            { "is_open", "1" }
        };
        using var dtResulte =
            await UtilityOfTuShare.GetTradeDataAsync("trade_cal", paramKey).ConfigureAwait(false);
        return dtResulte.ConvertTableToList<TradeCalendar>();
    }
}

/// <summary>
///  参数args:   null, null, tradedate 下载当日全部交易数据
///  参数args:   ts_code, startdate, enddate 下载单个股票数据
/// </summary>
internal class DownloadOnline_Daily : DownloadDataOnline<Daily>
{
    public override async Task<IList<Daily>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new();
        if (args.Length > 1)
        {
            paramKey.Add("ts_code", args[0]);
            paramKey.Add("start_date", args[1]);
            paramKey.Add("end_date", args[2]);
        }
        else
        {
            paramKey.Add("trade_date", args[0]);
        }

        using var dtDaily = await UtilityOfTuShare
            .GetTradeDataAsync("daily", paramKey).ConfigureAwait(false);
        using var dtAdjFactor = await UtilityOfTuShare
            .GetTradeDataAsync("adj_factor", paramKey).ConfigureAwait(false);
        IEnumerable<Daily> mergeBakDailes;
        if (args.Length > 1)
        {
            //下载当日全部交易数据
            mergeBakDailes = from trdata in dtDaily.ConvertTableToList<Daily>()
                             join adjdata in dtAdjFactor.ConvertTableToList<AdjFactor>()
                                 on trdata.Trade_date equals adjdata.Trade_date
                             orderby trdata.Trade_date
                             select new Daily
                             {
                                 Ts_code = trdata.Ts_code,
                                 Trade_date = trdata.Trade_date,
                                 Open = trdata.Open,
                                 High = trdata.High,
                                 Low = trdata.Low,
                                 Close = trdata.Close,
                                 Pre_close = trdata.Pre_close,
                                 Change = trdata.Change,
                                 Pct_chg = trdata.Pct_chg,
                                 Vol = trdata.Vol,
                                 Amount = trdata.Amount,
                                 Adj_factor = adjdata.Adj_factor
                             };
        }
        else
        {
            //下载单个股票期间交易数据
            mergeBakDailes = from trdata in dtDaily.ConvertTableToList<Daily>()
                             join adjdata in dtAdjFactor.ConvertTableToList<AdjFactor>()
                                 on trdata.Ts_code equals adjdata.Ts_code
                             orderby trdata.Ts_code
                             select new Daily
                             {
                                 Ts_code = trdata.Ts_code,
                                 Trade_date = trdata.Trade_date,
                                 Open = trdata.Open,
                                 High = trdata.High,
                                 Low = trdata.Low,
                                 Close = trdata.Close,
                                 Pre_close = trdata.Pre_close,
                                 Change = trdata.Change,
                                 Pct_chg = trdata.Pct_chg,
                                 Vol = trdata.Vol,
                                 Amount = trdata.Amount,
                                 Adj_factor = adjdata.Adj_factor
                             };
        }

        return mergeBakDailes.ToList();
    }
}

/// <summary>
///  参数args:   ts_code, startdate, enddate, null 单个股票财务数据下载
/// </summary>
internal class DownloadOnline_FinancialIndex : DownloadDataOnline<FinancialIndex>
{
    public override async Task<IList<FinancialIndex>> DownloadOnlineAsync(params string[] args)
    {
        using var dtFinancialIdx = await UtilityOfQuotesMoney.GetFinancialIndicators(args[0]).ConfigureAwait(false);
        return dtFinancialIdx.ConvertTableToList<FinancialIndex>(true)
            .Where(n =>
                string.Compare(n.ReportDt, args[1], StringComparison.CurrentCulture) >= 0 &&
                string.Compare(n.ReportDt, args[2], StringComparison.CurrentCulture) <= 0
            ).OrderBy(n => n.ReportDt).ToList();
    }
}

/// <summary>
/// 网易当日交易数据
/// 参数args:    ts_code, null, null, null
/// </summary>
internal class DownloadOnline_DailyOfQutoes : DownloadDataOnline<DailyOfQutoes>
{
    public override async Task<IList<DailyOfQutoes>> DownloadOnlineAsync(params string[] args)
    {
        return new List<DailyOfQutoes>
        {
            await UtilityOfQuotesMoney.GetTodayTradeData(args[0]).ConfigureAwait(false)
        };
    }
}
/// <summary>
/// 腾讯当日交易数据
/// 参数args:    ts_code, null, null, null
/// </summary>
internal class DownloadOnline_DailyOfTencent : DownloadDataOnline<DailyOfTencent>
{
    public override async Task<IList<DailyOfTencent>> DownloadOnlineAsync(params string[] args)
    {
        return new List<DailyOfTencent>
        {
            await UtilityOfTencent.GetTodayTradeData(args[0]).ConfigureAwait(false)
        };
    }
}

/// <summary>
///     网易分时线数据实现
/// </summary>
internal class DownloadOnline_MinuteOfQutoes : DownloadDataOnline<MinuteOfQutoes>
{
    public override async Task<IList<MinuteOfQutoes>> DownloadOnlineAsync(params string[] args)
    {
        return new List<MinuteOfQutoes>
        {
            await UtilityOfQuotesMoney.GetMintueTradeData(args[0]).ConfigureAwait(false)
        };
    }
}

internal class DownloadOnline_MinuteOfTencent : DownloadDataOnline<MinuteOfTencent>
{
    public override async Task<IList<MinuteOfTencent>> DownloadOnlineAsync(params string[] args)
    {
        return new List<MinuteOfTencent>
        {
            await UtilityOfTencent.GetMintueTradeData(args[0]).ConfigureAwait(false)
        };
    }
}

#endregion